package ren.nearby.http.di;


import com.google.gson.Gson;
import com.orhanobut.logger.Logger;

import org.json.JSONObject;
import org.json.JSONTokener;

import java.lang.reflect.Type;
import java.util.HashMap;

import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Function;
import ren.nearby.http.HttpResultBean4;
import ren.nearby.http.crypt.base64.BackAES;
import ren.nearby.http.crypt.rsa.Base64Decoder;
import ren.nearby.http.crypt.rsa.RSAUtils;
import ren.nearby.http.di.data.ResponseCallBack;
import ren.nearby.http.exception.Api2Exception;
import ren.nearby.http.utils.util.MD5;
import ren.nearby.http.utils.util.MD5Utils;
import ren.nearby.http.utils.util.RequestJsonUtil;


/**
 * Created by wukewei on 16/5/26.
 */
public class RxResultHelper {
    //http://www.jianshu.com/p/b1da0387f805
    public static <T> ObservableTransformer<HttpResultBean<T>, T> handleResult() {
        return new ObservableTransformer<HttpResultBean<T>, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<HttpResultBean<T>> upstream) {
                Logger.e("apply 1=  ");
                return upstream.flatMap(new Function<HttpResultBean<T>, ObservableSource<T>>() {
                    @Override
                    public ObservableSource<T> apply(@NonNull HttpResultBean<T> tHttpResultBean) throws Exception {
                        Logger.e("apply 2= " + tHttpResultBean.getData());
                       /* if (tHttpResultBean.getStatus() == 200) {
                            return createData(tHttpResultBean.getData());
                        } else {
                            return Observable.error(new Api2Exception(tHttpResultBean.getMsg()));
                        }*/
                        if (tHttpResultBean.getCount() > 0) {
                            return createData(tHttpResultBean.getMusics());
                        } else {
                            return Observable.error(new Api2Exception(tHttpResultBean.getMsg()));
                        }
                    }
                });
            }
        };
    }

    public static <T> ObservableTransformer<HttpResultBean3<T>, T> handleResult2() {
        return new ObservableTransformer<HttpResultBean3<T>, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<HttpResultBean3<T>> upstream) {
                return upstream.flatMap(new Function<HttpResultBean3<T>, ObservableSource<T>>() {
                    @Override
                    public ObservableSource<T> apply(@NonNull HttpResultBean3<T> tHttpResultBean3) throws Exception {
                        Logger.e("call... ");
                        if (tHttpResultBean3.getREP_BODY().getRSPCOD().equals("000000")) {
                            return createData2((T) tHttpResultBean3.getREP_BODY());
                        } else {
                            return Observable.error(new Api2Exception(tHttpResultBean3.getREP_BODY().getRSPMSG()));
                        }
                    }
                });
            }
        };
    }


    public static <T> ObservableTransformer<HttpsResultBean<T>, T> handleResult3(final Class o, final Type t) {
        return new ObservableTransformer<HttpsResultBean<T>, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<HttpsResultBean<T>> upstream) {
                return upstream.flatMap(
                        new Function<HttpsResultBean<T>, ObservableSource<T>>() {
                            @Override
                            public Observable<T> apply(HttpsResultBean<T> result) {
                                Logger.e("call... ");
                                if (result.getNstatus() == 200) {
                                    //解密
                                    Object value = encrypt(result.getNdata(), result.getNaesKey(), o, t);
                                    result.setData((T) value);
                                    return createData2(result.getData());
                                } else {
                                    return Observable.error(new Api2Exception(result.getNmsg()));
                                }

                            }
                        }
                );
            }
        };
    }

    //    https://juejin.im/post/5a94c19d6fb9a063577523a8
    public static <T> ObservableTransformer<HttpsResultBean<T>, T> handleResult4(final ResponseCallBack callback) {
        return new ObservableTransformer<HttpsResultBean<T>, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<HttpsResultBean<T>> upstream) {
                return upstream.flatMap(
                        new Function<HttpsResultBean<T>, ObservableSource<T>>() {
                            @Override
                            public Observable<T> apply(HttpsResultBean<T> result) {
                                Logger.e("apply 4= " + result.getContent());
                                if (result.getReturnCode() == 200) {
                                    callback.onToast(result.getReturnMsg());
                                    return createData(result.getContent());
                                } else {
                                    return Observable.error(new Api2Exception(result.getReturnMsg()));
                                }
                            }
                        }
                );
            }
        };
    }

    public static <T> ObservableTransformer<HttpResultBean4<T>, T> handleResult44() {
        return new ObservableTransformer<HttpResultBean4<T>, T>() {
            @Override
            public ObservableSource<T> apply(@NonNull Observable<HttpResultBean4<T>> upstream) {
                return upstream.flatMap(
                        new Function<HttpResultBean4<T>, ObservableSource<T>>() {
                            @Override
                            public Observable<T> apply(HttpResultBean4<T> result) {

                                if (result.getCode() == 200) {

                                    return createData(result.getResult());
                                } else {
                                    return Observable.error(new Api2Exception(result.getMessage()));
                                }
                            }
                        }
                );
            }
        };
    }


    /**
     * 解密
     *
     * @param result
     * @param naes
     * @return
     */
    public static Object encrypt(String result, String naes, Class o, Type t) {
        String value = null;
        Object msg = null;
        Gson gson = new Gson();
        try {
            long lStart = System.currentTimeMillis();
//                        //AES密钥和raw解密数据
            String strAes = new String(RSAUtils.decryptByPublicKeyForSpilt(Base64Decoder.decodeToBytes(naes), Base64Decoder.decodeToBytes(RSAUtils.publicKey)));
            value = BackAES.decrypt(result, strAes, 1);
            Logger.e("value = " + value);
            if (o != null) {
                msg = gson.fromJson(value, o);
            } else {
                msg = gson.fromJson(value, t);
            }
            long lUseTime = System.currentTimeMillis() - lStart;
            Logger.e("解密耗时：" + lUseTime + "毫秒");
            return msg;


        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }


    public static <T> Observable<T> createData(final T t) {
        return Observable.create(new ObservableOnSubscribe<T>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception {
                try {
                    emitter.onNext(t);
                    emitter.onComplete();
                } catch (Exception e) {
                    emitter.onError(e);
                }
            }
        });
    }

    public static <T> Observable<T> createData2(final T t) {
        return Observable.create(new ObservableOnSubscribe<T>() {
            @Override
            public void subscribe(@NonNull ObservableEmitter<T> emitter) throws Exception {
                try {
                    emitter.onNext(t);
                    emitter.onComplete();
                } catch (Exception e) {
                    emitter.onError(e);
                }
            }
        });
    }
}

